package com.zshy.base.core.utils;

import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.zshy.base.core.contract.constant.ContextConstants;
import com.zshy.base.core.contract.enums.AreaCodeEnum;
import com.zshy.base.core.contract.enums.ResultCodeEnum;
import com.zshy.base.core.contract.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 表单数据校验
 *
 * @author zhouhengzhe
 */
@Slf4j
public class FormValidatorUtils {

    /**
     * 私有构造方法
     */
    private FormValidatorUtils() {
    }


    /**
     * 邮件正则表达式
     */
    private static final Pattern EMAIL_REGEX = Pattern.compile(ContextConstants.EMAIL_PATTERN);

    /**
     * 中国的手机号码校验
     */
    private static final Pattern PHONE_REGEX = Pattern.compile(ContextConstants.PHONE_PATTERN);
    /**
     * QQ正则表达式
     */
    private static final Pattern QQ_REGEX = Pattern.compile(ContextConstants.QQ_PATTERN);

    /**
     * 身份证正则表达式
     */
    private static final Pattern ID_CARD_REGEX = Pattern.compile(ContextConstants.ID_CARD_PATTERN);

    /**
     * 校验日期格式：可以使用正则表达式进行校验
     */
    private static final Pattern DATE_REGEX = Pattern.compile(ContextConstants.DATE_PATTERN);

    /**
     * 校验URL：可以使用正则表达式进行校验
     * <p>
     * 注意：这个正则表达式可能不是完美的，但它可以处理许多常见的URL
     */
    private static final Pattern URL_REGEX = Pattern.compile(ContextConstants.URL_PATTERN);

    /**
     * 校验邮箱
     *
     * @param email 邮箱
     * @return
     */
    public static boolean validateEmail(String email) {
        BizAssert.assertBlankWarn(email, ResultCodeEnum.ARGUMENT_NULL);
        Matcher matcher = EMAIL_REGEX.matcher(email);
        return matcher.matches();
    }

    /**
     * 校验手机号
     *
     * @param phone 国际区号+手机号码
     * @return true: 校验通过
     */
    public static boolean validatePhone(String phone) {
        if (StringUtils.isBlank(phone)) {
            throw new ServiceException("手机号不能为空");
        }
        String[] phones = phone.split(",");
        //中国的，独立校验会比较安全点，当然也可以去掉这部分
        if (Objects.equals(ContextConstants.CHINA_COUNTRY_CODE, phones[0])) {
            Matcher matcher = PHONE_REGEX.matcher(phones[1]);
            return matcher.matches();
        } else {
            try {
                //国外的
                PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
                // 解析号码
                Phonenumber.PhoneNumber swissNumberProto = phoneNumberUtil.parse("+" + phones[0] + phones[1], AreaCodeEnum.getCodeEnumByCountryCode(phones[0]));
                // 校验号码
                return phoneNumberUtil.isValidNumber(swissNumberProto);
            } catch (NumberParseException e) {
                throw new ServiceException(e);
            }
        }
    }

    /**
     * @param qq
     * @return
     */
    public static boolean validateQq(String qq) {
        BizAssert.assertNullWarn(qq, ResultCodeEnum.ARGUMENT_NULL);
        Matcher matcher = QQ_REGEX.matcher(qq);
        return matcher.matches();
    }

    /**
     * 验证日期格式是否合法
     *
     * @param date 待验证的日期字符串，格式应为yyyy-MM-dd
     * @return 如果日期格式合法，则返回true；否则返回false
     * @throws IllegalArgumentException 如果传入的日期字符串为空，则抛出该异常
     */
    public static boolean validateDate(String date) {
        BizAssert.assertBlankWarn(date, ResultCodeEnum.ARGUMENT_NULL);
        Matcher matcher = DATE_REGEX.matcher(date);
        return matcher.matches();
    }

    /**
     * 验证给定的字符串是否符合URL的格式。
     *
     * @param url 要验证的字符串，不能为null。
     * @return 如果给定的字符串符合URL的格式，则返回true；否则返回false。
     */
    public static boolean validateUrl(String url) {
        BizAssert.assertBlankWarn(url, ResultCodeEnum.ARGUMENT_NULL);
        Matcher matcher = URL_REGEX.matcher(url);
        return matcher.matches();
    }
}